/* 添加请求拦截器
拦截 request 请求
拦截 uploadFile 文件上传
需要实现功能:
 1. URL地址拼接
 2. 设置请求超时时间
 3. 添加小程序端请求头标识
 4. 添加 token 请求头标识
*/
import { useMemberStore } from '@/stores'
// 获取用户仓库对象
const memberStore = useMemberStore()

// 服务器基础地址
// const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net' // 开发服务器
// 添加请求拦截器
const httpInterceptor = {
  // 拦截前触发invoke函数
  invoke(options: UniApp.RequestOptions) {
    // 1. URL地址拼接
    if (!options.url.startsWith('http')) {
      options.url = import.meta.env.VITE_SERVER_URL + options.url
    }
    // 2. 设置请求超时时间 默认 60s
    options.timeout = 10000 // 毫秒
    // 3. 添加小程序端请求头标识
    options.header = {
      ...options.header,
      'source-client': 'miniapp',
    }
    // 4. 添加 token 请求头标识
    // 从用户仓库中获取token
    const token = memberStore.profile?.token
    if (token) {
      options.header.Authorization = token
    }
  },
}
// 为 request,uploadFile 添加拦截器
uni.addInterceptor('request', httpInterceptor)
// uni.addInterceptor('uploadFile', httpInterceptor)

/**
 * 请求函数
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象，用于处理返回值类型
 *  2. 获取数据成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型，支持泛型
 *  3. 获取数据失败
 *    3.1 401错误  -> 清理用户信息，跳转到登录页
 *    3.2 其他错误 -> 根据后端错误信息轻提示
 *    3.3 网络错误 -> 提示用户换网络
 */
// 定义返回数据的类型 返回数据的类型由接口方法调用时传递的泛型决定
interface Data<T> {
  code: string
  msg: string
  result: T
}
// 2.2 添加类型，支持泛型
// 简化请求函数
export const http = {
  request: <T>(options: UniApp.RequestOptions) => {
    // 1. 返回 Promise 对象
    return new Promise<Data<T>>((resolve, reject) => {
      uni.request({
        ...options,
        // 2. 请求成功
        async success(res: UniApp.RequestSuccessCallbackResult) {
          // 判断响应状态码
          if (res.statusCode >= 200 && res.statusCode < 300) {
            // 状态码2xx
            // 判断响应状态码 res.data.code==='1' 表示请求成功
            const code = (res.data as Data<T>).code
            if (code === '1') {
              // 提取核心数据 res.data
              resolve(res.data as Data<T>)
            } else {
              // 请求错误未返回数据
              uni.showToast({
                title: (res.data as Data<T>).msg || '请求错误',
                icon: 'none',
              })
              reject(res.data)
            }
            // 2.1 提取核心数据 res.data
            // resolve(res.data as Data<T>)
          } else if (res.statusCode === 401) {
            // 提示用户登录过期重新登录
            const modalRes = await uni.showModal({
              title: '提示',
              content: '登录过期，请重新登录',
              showCancel: false,
              mask: true,
            })
            // 用户点击确定按钮
            if (modalRes.confirm) {
              // 状态码401: token失效
              // 清除用户信息
              memberStore.clearProfile()
              // 跳转到微信登录页面
              uni.navigateTo({
                url: '/pages/login/login',
              })
              reject(res)
            }
          } else {
            // 其他错误
            uni.showToast({
              title: (res.data as Data<T>).msg || '请求错误',
              icon: 'none',
            })
            reject(res)
          }
        },
        // 请求失败(网络错误)
        fail(err) {
          uni.showToast({
            title: '请检查网络连接',
            icon: 'none',
            mask: true,
          })
          reject(err)
        },
      })
    })
  },
  get: <T>(url: string, data = {}, config = {}) => {
    return http.request<T>({
      url,
      method: 'GET',
      data,
      ...config,
    })
  },
  post: <T>(url: string, data = {}, config = {}) => {
    return http.request<T>({
      url,
      method: 'POST',
      data,
      ...config,
    })
  },
  put: <T>(url: string, data = {}, config = {}) => {
    return http.request<T>({
      url,
      method: 'PUT',
      data,
      ...config,
    })
  },
  delete: <T>(url: string, data = {}, config = {}) => {
    return http.request<T>({
      url,
      method: 'DELETE',
      data,
      ...config,
    })
  },
  upload: <T>({ url = '', filePath = '', name = 'file', config = {} }) => {
    return new Promise<Data<T>>((resolve, reject) => {
      uni.uploadFile({
        ...config,
        // url, 接口暂时通
        filePath,
        name,
        // 使用尚硅谷上传头像接口
        url: 'https://gmall-prod.atguigu.cn/mall-api' + url,
        header: {
          token:
            'eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAKtWKi5NUrJScgwN8dANDXYNUtJRSq0oULIyNDcysjQxtLQ011EqLU4t8kwBiuko5SXmpgKVP9uy6nnjaiBSqgUAA0qU4EIAAAA.G4QL8RhgFTDlBkPu32O2swNN4MIbMl1wttdNpt2bYhw86iZN1ppkNWvZvsFS0mXpcR0p6C7Q821FfnXOhbohEQ',
        },
        // 上传成功
        async success(res: UniApp.UploadFileSuccessCallbackResult) {
          // 判断响应状态码
          if (res.statusCode >= 200 && res.statusCode < 300) {
            // 状态码2xx
            // 2.1 提取核心数据 res.data
            resolve(JSON.parse(res.data as string))
          } else {
            // 其他错误
            uni.showToast({
              title: JSON.parse(res.data as string).msg || '请求错误',
              icon: 'none',
            })
            reject(res)
          }
        },
        // 请求失败(网络错误)
        fail(err) {
          uni.showToast({
            title: '请检查网络连接',
            icon: 'none',
            mask: true,
          })
          reject(err)
        },
      })
    })
  },
}
